﻿using System;
using System.ComponentModel;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using XamlingCore.Infrastructure.Event;

namespace XamlingCore.SL.Controls.Chrome
{

    /// <summary>
    /// This taken from http://silverlightfeeds.com/post/1786/Chromeless_Window_for_OOB_applications_in_Silverlight_4.0_RC.aspx
    /// </summary>
    [TemplatePart(Name = ApplicationWindow.CloseButtonName, Type = typeof(ButtonBase))]
    [TemplatePart(Name = ApplicationWindow.MaximizeButtonName, Type = typeof(ButtonBase))]
    [TemplatePart(Name = ApplicationWindow.MinimizeButtonName, Type = typeof(ButtonBase))]
    [TemplatePart(Name = ApplicationWindow.ChromeName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = ApplicationWindow.ResizeHandleName, Type = typeof(FrameworkElement))]
    public class ApplicationWindow : ContentControl
    {
        public EventHandler<EventArgs> Closed;
        public EventHandler<CancelEventArgs> Closing;

        /// <summary>
        /// Gets or sets the close button.
        /// </summary>
        /// <value>The close button.</value>
        private const string CloseButtonName = "CloseButton";
        private ButtonBase CloseButton { get; set; }

        /// <summary>
        /// Gets or sets the maximize button.
        /// </summary>
        /// <value>The maximize button.</value>
        private const string MaximizeButtonName = "MaximizeButton";
        private ButtonBase MaximizeButton { get; set; }

        /// <summary>
        /// Gets or sets the minimize button.
        /// </summary>
        /// <value>The minimize button.</value>
        private const string MinimizeButtonName = "MinimizeButton";
        private ButtonBase MinimizeButton { get; set; }

        /// <summary>
        /// Gets or sets the chrome.
        /// </summary>
        /// <value>The chrome.</value>
        private const string ChromeName = "Chrome";
        private FrameworkElement Chrome { get; set; }

        /// <summary>
        /// Gets or sets the resize handle.
        /// </summary>
        /// <value>The resize handle.</value>
        private const string ResizeHandleName = "ResizeHandle";
        private FrameworkElement ResizeHandle { get; set; }

        #region TitleProperty

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(ApplicationWindow), new PropertyMetadata(string.Empty));

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationWindow"/> class.
        /// </summary>
        public ApplicationWindow()
        {
            this.DefaultStyleKey = typeof(ApplicationWindow);
        }

        /// <summary>
        /// When overridden in a derived class, is invoked whenever application code or internal processes (such as a rebuilding layout pass) call <see cref="M:System.Windows.Controls.Control.ApplyTemplate"/>. In simplest terms, this means the method is called just before a UI element displays in an application, but see Remarks for more information.
        /// </summary>
        public override void OnApplyTemplate()
        {
            this.CloseButton = (ButtonBase)this.GetTemplateChild(ApplicationWindow.CloseButtonName);
            if (CloseButton != null)
            {
                this.CloseButton.Click += new RoutedEventHandler(CloseButton_Click);
            }

            this.MinimizeButton = (ButtonBase)this.GetTemplateChild(ApplicationWindow.MinimizeButtonName);
            if (MinimizeButton != null)
            {
                this.MinimizeButton.Click += new RoutedEventHandler(MinimizeButton_Click);
            }

            this.MaximizeButton = (ButtonBase)this.GetTemplateChild(ApplicationWindow.MaximizeButtonName);

            if (MaximizeButton != null)
            {
                this.MaximizeButton.Click += new RoutedEventHandler(MaximizeButton_Click);
            }

            this.Chrome = (FrameworkElement)this.GetTemplateChild(ApplicationWindow.ChromeName);
            if (Chrome != null)
            {
                this.Chrome.MouseLeftButtonDown += new MouseButtonEventHandler(Chrome_MouseLeftButtonDown);
            }

            this.ResizeHandle = (FrameworkElement)this.GetTemplateChild(ApplicationWindow.ResizeHandleName);
            if (ResizeHandle != null)
            {
                this.ResizeHandle.MouseLeftButtonDown += new MouseButtonEventHandler(ResizeHandle_MouseLeftButtonDown);
            }

            base.OnApplyTemplate();
        }

        /// <summary>
        /// Handles the MouseLeftButtonDown event of the Chrome control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        void Chrome_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (Application.Current.IsRunningOutOfBrowser && Application.Current.HasElevatedPermissions)
                Application.Current.MainWindow.DragMove();
        }

        /// <summary>
        /// Handles the MouseLeftButtonDown event of the ResizeHandle control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        void ResizeHandle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (Application.Current.IsRunningOutOfBrowser && Application.Current.HasElevatedPermissions)
                Application.Current.MainWindow.DragResize(WindowResizeEdge.BottomRight);
        }

        /// <summary>
        /// Handles the Click event of the CloseButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            CancelEventArgs args = new CancelEventArgs();
            this.Closing.Raise(this, args);

            if (Application.Current.IsRunningOutOfBrowser && Application.Current.HasElevatedPermissions && !args.Cancel)
            {
                Application.Current.MainWindow.Close();
                this.Closed.Raise(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Handles the Click event of the MaximizeButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (Application.Current.IsRunningOutOfBrowser && Application.Current.HasElevatedPermissions)
            {
                if (Application.Current.MainWindow.WindowState == WindowState.Normal)
                    Application.Current.MainWindow.WindowState = WindowState.Maximized;
                else
                    Application.Current.MainWindow.WindowState = WindowState.Normal;
            }
        }

        /// <summary>
        /// Handles the Click event of the MinimizeButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        void MinimizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (Application.Current.IsRunningOutOfBrowser && Application.Current.HasElevatedPermissions)
                Application.Current.MainWindow.WindowState = WindowState.Minimized;
        }
    }
}
